package com.xb.chain.netty.server;

import com.xb.chain.config.BlockChainProperties;
import com.xb.chain.constant.InfoConstant;
import com.xb.chain.dao.HostInfoDao;
import com.xb.chain.entity.ConnectionInfo;
import com.xb.chain.netty.client.NodeClientStart;
import com.xb.chain.netty.message.handle.ClientToServerMessage;
import com.xb.chain.netty.message.handle.MessageHandle;
import com.xb.chain.utils.SpringContextUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author xiaobin
 * @date 2020/2/22 18:52
 * @desc 节点 netty TCP 服务端
 */
@Slf4j(topic = "nodeServerStart")
public class NodeServerStart {

    private static ExecutorService executorService = Executors.newFixedThreadPool(InfoConstant.THREAD_POOL_SIZE);
    public static volatile NodeState nodeState = NodeState.NODE_READY;

    public static BlockChainProperties blockChainProperties;

    static {
        blockChainProperties = SpringContextUtil.getBean(BlockChainProperties.class);
        executorService.execute(new NodeStateTask());
        executorService.execute(() -> {
            MessageHandle.queueStart();
        });
    }

    public static void start() {
        executorService.execute(() -> {
            EventLoopGroup bossGroup = new NioEventLoopGroup(1);
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {

                ServerBootstrap serverBootstrap = new ServerBootstrap().group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class).childHandler(new NodeServerChannelInit());
                ChannelFuture sync = serverBootstrap.bind(new InetSocketAddress(NodeServerStart.blockChainProperties.getServerIp(), NodeServerStart.blockChainProperties.getPort())).sync();
                log.info("节点服务端启动成功");
                nodeState = NodeState.NODE_REG;
                sync.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                log.error("节点服务端启动异常：{}", e);
            } finally {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        });

    }

    public static void noticeOtherNode() {
        try {
            Thread.sleep(10000);
            ClientToServerMessage.newNodeAdd();
            // 初次启动，同步节点数据
            Thread.sleep(8000);
            ClientToServerMessage.initSyncNode();
            nodeState = NodeState.NODE_SUCCESS;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 客户端连接所有服务器
    public static void registerInfo() {
        // 1、注册Mysql服务端信息
        HostInfoDao.insert(ConnectionInfo.builder().ip(NodeServerStart.blockChainProperties.getServerIp()).port(NodeServerStart.blockChainProperties.getPort()).build());
        // 2、启动客户端连接节点服务器
        List<ConnectionInfo> nodeList = HostInfoDao.getNodeList();
        nodeList.stream().forEach((item) -> {
            NodeClientStart.serverConnection(item.getIp(), item.getPort());
        });
        nodeState = NodeState.NODE_NOTICE;
    }

}
